/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ulwx.tool;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.sql.rowset.CachedRowSet;

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import net.sf.json.util.PropertyFilter;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.rits.cloning.Cloner;
import com.sun.rowset.CachedRowSetImpl;
import com.ulwx.database.DataBaseKeyMap;
import com.ulwx.database.DataBaseSet;
import com.ulwx.database.sql.SqlUtils;

/**
 * Miscellaneous object utility methods. Mainly for internal use within the
 * framework; consider Jakarta's Commons Lang for a more comprehensive suite of
 * object utilities.
 * 
 * @author Juergen Hoeller
 * @author Keith Donald
 * @author Rod Johnson
 * @author Rob Harrop
 * @author Alex Ruiz
 * @since 19.03.2004
 * @see org.apache.commons.lang.ObjectUtils
 */
public abstract class ObjectUtils {
	private static final Logger log = Logger.getLogger(ObjectUtils.class);
	private static final int INITIAL_HASH = 7;
	private static final int MULTIPLIER = 31;

	private static final String EMPTY_STRING = "";
	private static final String NULL_STRING = "null";
	private static final String ARRAY_START = "{";
	private static final String ARRAY_END = "}";
	private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
	private static final String ARRAY_ELEMENT_SEPARATOR = ", ";

	/**
	 * Return whether the given throwable is a checked exception: that is,
	 * neither a RuntimeException nor an Error.
	 * 
	 * @param ex
	 *            the throwable to check
	 * @return whether the throwable is a checked exception
	 * @see java.lang.Exception
	 * @see java.lang.RuntimeException
	 * @see java.lang.Error
	 */
	public static boolean isCheckedException(Throwable ex) {
		return !(ex instanceof RuntimeException || ex instanceof Error);
	}

	/**
	 * 
	 * @param o
	 *            要序列化的对象，必须遵循java序列化对象的要求,即对象是可序列化的
	 * @return 对象对象的字节数组
	 * @throws Exception
	 */
	public static byte[] serializeObject(Object o) throws Exception {
		ByteArrayOutputStream bos = null;
		ObjectOutputStream oos = null;
		if (o == null) {
			return null;
		}

		try {
			bos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bos);
			oos.writeObject(o);
			oos.flush();
			return bos.toByteArray();
		} finally {
			if (oos != null) {
				oos.close();
			}
		}
	}

	/**
	 * 
	 * @param data
	 *            对象序列化字节流
	 * @return 反序列化的对象
	 * @throws Exception
	 */
	public static Object deSerializeObject(byte[] data) throws Exception {
		ByteArrayInputStream bis = null;
		ObjectInputStream ois = null;
		if (data == null || data.length == 0) {
			return null;
		}
		try {
			bis = new ByteArrayInputStream(data);
			ois = new ObjectInputStream(bis);
			return ois.readObject();
		} finally {
			if (ois != null) {
				ois.close();
			}
		}
	}

	// 序列化对象
	public static String converToString(Object value, boolean isCompress)
			throws Exception {
		if (value != null)// 如果要设置的值非空，那么就需要先序列化，然后转化为String
		{
			try {
				byte[] b = serializeObject(value);
				if (isCompress) {
					b = ZipUtils.gzip(b);
				}
				String result = new String(b, "iso-8859-1");
				log.error("converToString===" + result);
				return result;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				// e.printStackTrace();
				throw e;
			}

		} else {
			return null;
		}

	}

	// 反序列化对象
	public static Object converToObject(String value, boolean isCompress)
			throws Exception {
		log.error("converToObject1111111111===" + value);
		try {
			if (value != null) {
				byte[] b = value.getBytes("iso-8859-1");
				if (isCompress) {
					b = ZipUtils.ungzip(b);
				}
				// Object
				// result=deSerializeObject(ZipUtils.ungzip(value.getBytes("iso-8859-1")));
				Object result = deSerializeObject(b);
				return result;
			} else {
				return null;
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			throw e;
		}
	}

	/**
	 * Check whether the given exception is compatible with the exceptions
	 * declared in a throws clause.
	 * 
	 * @param ex
	 *            the exception to checked
	 * @param declaredExceptions
	 *            the exceptions declared in the throws clause
	 * @return whether the given exception is compatible
	 */
	public static boolean isCompatibleWithThrowsClause(Throwable ex,
			Class[] declaredExceptions) {
		if (!isCheckedException(ex)) {
			return true;
		}
		if (declaredExceptions != null) {
			for (int i = 0; i < declaredExceptions.length; i++) {
				if (declaredExceptions[i].isAssignableFrom(ex.getClass())) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Return whether the given array is empty: that is, <code>null</code> or of
	 * zero length.
	 * 
	 * @param array
	 *            the array to check
	 * @return whether the given array is empty
	 */
	public static boolean isEmpty(Object[] array) {
		return (array == null || array.length == 0);
	}

	/**
	 * Append the given Object to the given array, returning a new array
	 * consisting of the input array contents plus the given Object.
	 * 
	 * @param array
	 *            the array to append to (can be <code>null</code>)
	 * @param obj
	 *            the Object to append
	 * @return the new array (of the same component type; never
	 *         <code>null</code>)
	 */
	public static Object[] addObjectToArray(Object[] array, Object obj) {
		Class compType = Object.class;
		if (array != null) {
			compType = array.getClass().getComponentType();
		} else if (obj != null) {
			compType = obj.getClass();
		}
		int newArrLength = (array != null ? array.length + 1 : 1);
		Object[] newArr = (Object[]) Array.newInstance(compType, newArrLength);
		if (array != null) {
			System.arraycopy(array, 0, newArr, 0, array.length);
		}
		newArr[newArr.length - 1] = obj;
		return newArr;
	}

	/**
	 * Convert the given array (which may be a primitive array) to an object
	 * array (if necessary of primitive wrapper objects).
	 * <p>
	 * A <code>null</code> source value will be converted to an empty Object
	 * array.
	 * 
	 * @param source
	 *            the (potentially primitive) array
	 * @return the corresponding object array (never <code>null</code>)
	 * @throws IllegalArgumentException
	 *             if the parameter is not an array
	 */
	public static Object[] toObjectArray(Object source) {
		if (source instanceof Object[]) {
			return (Object[]) source;
		}
		if (source == null) {
			return new Object[0];
		}
		if (!source.getClass().isArray()) {
			throw new IllegalArgumentException("Source is not an array: "
					+ source);
		}

		int length = Array.getLength(source);
		if (length == 0) {
			return new Object[0];
		}
		Class wrapperType = Array.get(source, 0).getClass();
		Object[] newArray = (Object[]) Array.newInstance(wrapperType, length);
		for (int i = 0; i < length; i++) {
			newArray[i] = Array.get(source, i);
		}
		return newArray;
	}

	// ---------------------------------------------------------------------
	// Convenience methods for content-based equality/hash-code handling
	// ---------------------------------------------------------------------

	/**
	 * Determine if the given objects are equal, returning <code>true</code> if
	 * both are <code>null</code> or <code>false</code> if only one is
	 * <code>null</code>.
	 * <p>
	 * Compares arrays with <code>Arrays.equals</code>, performing an equality
	 * check based on the array elements rather than the array reference.
	 * 
	 * @param o1
	 *            first Object to compare
	 * @param o2
	 *            second Object to compare
	 * @return whether the given objects are equal
	 * @see java.util.Arrays#equals
	 */
	public static boolean nullSafeEquals(Object o1, Object o2) {
		if (o1 == o2) {
			return true;
		}
		if (o1 == null || o2 == null) {
			return false;
		}
		if (o1.equals(o2)) {
			return true;
		}
		if (o1 instanceof Object[] && o2 instanceof Object[]) {
			return Arrays.equals((Object[]) o1, (Object[]) o2);
		}
		if (o1 instanceof boolean[] && o2 instanceof boolean[]) {
			return Arrays.equals((boolean[]) o1, (boolean[]) o2);
		}
		if (o1 instanceof byte[] && o2 instanceof byte[]) {
			return Arrays.equals((byte[]) o1, (byte[]) o2);
		}
		if (o1 instanceof char[] && o2 instanceof char[]) {
			return Arrays.equals((char[]) o1, (char[]) o2);
		}
		if (o1 instanceof double[] && o2 instanceof double[]) {
			return Arrays.equals((double[]) o1, (double[]) o2);
		}
		if (o1 instanceof float[] && o2 instanceof float[]) {
			return Arrays.equals((float[]) o1, (float[]) o2);
		}
		if (o1 instanceof int[] && o2 instanceof int[]) {
			return Arrays.equals((int[]) o1, (int[]) o2);
		}
		if (o1 instanceof long[] && o2 instanceof long[]) {
			return Arrays.equals((long[]) o1, (long[]) o2);
		}
		if (o1 instanceof short[] && o2 instanceof short[]) {
			return Arrays.equals((short[]) o1, (short[]) o2);
		}
		return false;
	}

	/**
	 * Return as hash code for the given object; typically the value of
	 * <code>{@link Object#hashCode()}</code>. If the object is an array, this
	 * method will delegate to any of the <code>nullSafeHashCode</code> methods
	 * for arrays in this class. If the object is <code>null</code>, this method
	 * returns 0.
	 * 
	 * @see #nullSafeHashCode(Object[])
	 * @see #nullSafeHashCode(boolean[])
	 * @see #nullSafeHashCode(byte[])
	 * @see #nullSafeHashCode(char[])
	 * @see #nullSafeHashCode(double[])
	 * @see #nullSafeHashCode(float[])
	 * @see #nullSafeHashCode(int[])
	 * @see #nullSafeHashCode(long[])
	 * @see #nullSafeHashCode(short[])
	 */
	public static int nullSafeHashCode(Object obj) {
		if (obj == null) {
			return 0;
		}
		if (obj instanceof Object[]) {
			return nullSafeHashCode((Object[]) obj);
		}
		if (obj instanceof boolean[]) {
			return nullSafeHashCode((boolean[]) obj);
		}
		if (obj instanceof byte[]) {
			return nullSafeHashCode((byte[]) obj);
		}
		if (obj instanceof char[]) {
			return nullSafeHashCode((char[]) obj);
		}
		if (obj instanceof double[]) {
			return nullSafeHashCode((double[]) obj);
		}
		if (obj instanceof float[]) {
			return nullSafeHashCode((float[]) obj);
		}
		if (obj instanceof int[]) {
			return nullSafeHashCode((int[]) obj);
		}
		if (obj instanceof long[]) {
			return nullSafeHashCode((long[]) obj);
		}
		if (obj instanceof short[]) {
			return nullSafeHashCode((short[]) obj);
		}
		return obj.hashCode();
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(Object[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + nullSafeHashCode(array[i]);
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(boolean[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + hashCode(array[i]);
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(byte[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + array[i];
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(char[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + array[i];
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(double[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + hashCode(array[i]);
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(float[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + hashCode(array[i]);
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(int[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + array[i];
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(long[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + hashCode(array[i]);
		}
		return hash;
	}

	/**
	 * Return a hash code based on the contents of the specified array. If
	 * <code>array</code> is <code>null</code>, this method returns 0.
	 */
	public static int nullSafeHashCode(short[] array) {
		if (array == null) {
			return 0;
		}
		int hash = INITIAL_HASH;
		int arraySize = array.length;
		for (int i = 0; i < arraySize; i++) {
			hash = MULTIPLIER * hash + array[i];
		}
		return hash;
	}

	/**
	 * Return the same value as <code>{@link Boolean#hashCode()}</code>.
	 * 
	 * @see Boolean#hashCode()
	 */
	public static int hashCode(boolean bool) {
		return bool ? 1231 : 1237;
	}

	/**
	 * Return the same value as <code>{@link Double#hashCode()}</code>.
	 * 
	 * @see Double#hashCode()
	 */
	public static int hashCode(double dbl) {
		long bits = Double.doubleToLongBits(dbl);
		return hashCode(bits);
	}

	/**
	 * Return the same value as <code>{@link Float#hashCode()}</code>.
	 * 
	 * @see Float#hashCode()
	 */
	public static int hashCode(float flt) {
		return Float.floatToIntBits(flt);
	}

	/**
	 * Return the same value as <code>{@link Long#hashCode()}</code>.
	 * 
	 * @see Long#hashCode()
	 */
	public static int hashCode(long lng) {
		return (int) (lng ^ (lng >>> 32));
	}

	// ---------------------------------------------------------------------
	// Convenience methods for toString output
	// ---------------------------------------------------------------------

	/**
	 * Return a String representation of an object's overall identity.
	 * 
	 * @param obj
	 *            the object (may be <code>null</code>)
	 * @return the object's identity as String representation, or
	 *         <code>null</code> if the object was <code>null</code>
	 */
	public static String identityToString(Object obj) {
		if (obj == null) {
			return EMPTY_STRING;
		}
		return obj.getClass().getName() + "@" + getIdentityHexString(obj);
	}

	/**
	 * Return a hex String form of an object's identity hash code.
	 * 
	 * @param obj
	 *            the object
	 * @return the object's identity code in hex notation
	 */
	public static String getIdentityHexString(Object obj) {
		return Integer.toHexString(System.identityHashCode(obj));
	}

	/**
	 * Return a content-based String representation if <code>obj</code> is not
	 * <code>null</code>; otherwise returns an empty String.
	 * <p>
	 * Differs from {@link #nullSafeToString(Object)} in that it returns an
	 * empty String rather than "null" for a <code>null</code> value.
	 * 
	 * @param obj
	 *            the object to build a display String for
	 * @return a display String representation of <code>obj</code>
	 * @see #nullSafeToString(Object)
	 */
	public static String getDisplayString(Object obj) {
		if (obj == null) {
			return EMPTY_STRING;
		}
		return nullSafeToString(obj);
	}

	/**
	 * Determine the class name for the given object.
	 * <p>
	 * Returns <code>"null"</code> if <code>obj</code> is <code>null</code>.
	 * 
	 * @param obj
	 *            the object to introspect (may be <code>null</code>)
	 * @return the corresponding class name
	 */
	public static String nullSafeClassName(Object obj) {
		return (obj != null ? obj.getClass().getName() : NULL_STRING);
	}

	/**
	 * Return a String representation of the specified Object.
	 * <p>
	 * Builds a String representation of the contents in case of an array.
	 * Returns <code>"null"</code> if <code>obj</code> is <code>null</code>.
	 * 
	 * @param obj
	 *            the object to build a String representation for
	 * @return a String representation of <code>obj</code>
	 */
	public static String nullSafeToString(Object obj) {
		if (obj == null) {
			return NULL_STRING;
		}
		if (obj instanceof String) {
			return (String) obj;
		}
		if (obj instanceof Object[]) {
			return nullSafeToString((Object[]) obj);
		}
		if (obj instanceof boolean[]) {
			return nullSafeToString((boolean[]) obj);
		}
		if (obj instanceof byte[]) {
			return nullSafeToString((byte[]) obj);
		}
		if (obj instanceof char[]) {
			return nullSafeToString((char[]) obj);
		}
		if (obj instanceof double[]) {
			return nullSafeToString((double[]) obj);
		}
		if (obj instanceof float[]) {
			return nullSafeToString((float[]) obj);
		}
		if (obj instanceof int[]) {
			return nullSafeToString((int[]) obj);
		}
		if (obj instanceof long[]) {
			return nullSafeToString((long[]) obj);
		}
		if (obj instanceof short[]) {
			return nullSafeToString((short[]) obj);
		}
		String str = obj.toString();
		return (str != null ? str : EMPTY_STRING);
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(Object[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}
			buffer.append(String.valueOf(array[i]));
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(boolean[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}

			buffer.append(array[i]);
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(byte[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}
			buffer.append(array[i]);
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(char[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}
			buffer.append("'").append(array[i]).append("'");
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(double[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}

			buffer.append(array[i]);
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(float[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}

			buffer.append(array[i]);
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(int[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}
			buffer.append(array[i]);
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(long[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}
			buffer.append(array[i]);
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * Return a String representation of the contents of the specified array.
	 * <p>
	 * The String representation consists of a list of the array's elements,
	 * enclosed in curly braces (<code>"{}"</code>). Adjacent elements are
	 * separated by the characters <code>", "</code> (a comma followed by a
	 * space). Returns <code>"null"</code> if <code>array</code> is
	 * <code>null</code>.
	 * 
	 * @param array
	 *            the array to build a String representation for
	 * @return a String representation of <code>array</code>
	 */
	public static String nullSafeToString(short[] array) {
		if (array == null) {
			return NULL_STRING;
		}
		int length = array.length;
		if (length == 0) {
			return EMPTY_ARRAY;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				buffer.append(ARRAY_START);
			} else {
				buffer.append(ARRAY_ELEMENT_SEPARATOR);
			}
			buffer.append(array[i]);
		}
		buffer.append(ARRAY_END);
		return buffer.toString();
	}

	/**
	 * 把json对象转换成一个map对象
	 * 
	 * @param obj
	 * @return
	 */
	public static Map<String, Object> fromJavaBeanToMap(Object obj) {
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> fieldMap = mapper.convertValue(obj, Map.class);
		return fieldMap;
	}

	/**
	 * 把json字符串转换成指定type的对象
	 * 
	 * @param <T>
	 * @param json
	 * @param type
	 * @return
	 * @throws Exception
	 */
	public static <T> T fromJsonToObject(String json, Class<T> type)
			throws Exception {

		// ObjectMapper mapper = new ObjectMapper();
		// T obj = mapper.readValue(json, type);
		// return obj;
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat("yyyy-MM-dd HH:mm:ss");

		Gson gson = builder.create();
		T target = gson.fromJson(json, type);
		return target;

	}

	/**
	 * 
	 * @param <T>
	 * @param json
	 * @param type
	 *            Type typeOfT = new
	 *            com.google.gson.reflect.TypeToken<Collection
	 *            <Foo>>(){}.getType();
	 * @return
	 * @throws Exception
	 */
	public static Object fromJsonToObject(String json, Type type)
			throws Exception {

		// ObjectMapper mapper = new ObjectMapper();
		// T obj = mapper.readValue(json, type);
		// return obj;

		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat("yyyy-MM-dd HH:mm:ss");

		Gson gson = builder.create();

		// Gson gson=new Gson();
		Object target = gson.fromJson(json, type);
		return target;

	}

	/**
	 * 使json字符串转换成java的jdk内部对象 Object -->LinkedHashMap<String,Object>
	 * array-->ArrayList<Object> string-->String number (no fraction)-->Integer,
	 * Long or BigInteger (smallest applicable) number (fraction) -->Double
	 * (configurable to use BigDecimal) true|false -->Boolean null --> null
	 * 
	 * @param json
	 * @return
	 * @throws Exception
	 */
	public static Object fromJsonToObject(String json) throws Exception {

		ObjectMapper mapper = new ObjectMapper();
		Object obj = mapper.readValue(json, Object.class);

		return obj;
	}

	public static Object fromJsonTobject(String json) throws Exception {

		return fromJsonToObject(json);
	}

	public static String toJsonString(Object obj) {
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat("yyyy-MM-dd HH:mm:ss");

		Gson gson = builder.create();

		String target = gson.toJson(obj);
		return target;

	}

	public static String toJsonString(Object obj, String dateFormate) {
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat(dateFormate);

		Gson gson = builder.create();

		String target = gson.toJson(obj);
		return target;

	}

	public static String toJsonString(Object obj, Type t, String dateFormate) {
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat(dateFormate);

		Gson gson = builder.create();

		String target = gson.toJson(obj, t);
		return target;

	}

	public static String toJsonString(Object obj, Type t) {
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat("yyyy-MM-dd HH:mm:ss");

		Gson gson = builder.create();

		String target = gson.toJson(obj, t);
		return target;

	}

	public static boolean isPrimitiveWapper(Class t) {
		if (t == Integer.class || t == Boolean.class || t == Long.class

		|| t == Short.class || t == Float.class || t == Double.class
				|| t == Byte.class || t == Character.class) {
			return true;
		}
		return false;

	}
	
	/**
	 * 把rs的一行转换成一个javabean
	 * @param <T>
	 * @param clazz
	 * @param rs
	 * @return
	 */
	public static <T> T getBeanFromResultSet(Class<T> clazz, ResultSet rs) {

		try {

			T bean = clazz.newInstance();
			// Map<String, Object> nestedObjs = new HashMap<String,
			// Object>();
			Map<?, ?> map = PropertyUtils.describe(bean);
			Set<?> set = map.keySet();
			Iterator<?> i = set.iterator();

			while (i.hasNext()) {

				String name = (String) i.next();
				// System.err.println("bean:propertye:" + name);
				// Class t=PropertyUtils.getPropertyType(bean,name);
				// Object value=map.get(name);
				if (name.equals("class"))
					continue;

				Class<?> t = PropertyUtils.getPropertyType(bean, name);
				Object value = null;

				// name为javabean属性名
				if (SqlUtils.checkedSimpleType(t)) {// 简单类型

					value = SqlUtils.getValueFromResult(t, "", name, rs,
							DataBaseKeyMap.getMap());
					PropertyUtils.setProperty(bean, name, value);
				} else {
					log.info("不识别的类型["+t.getSimpleName()+"]");
				}

			}// while

			return bean;
		} catch (Exception e) {
			log.error("", e);
		}
		return null;

	}
	
	/**
	 * 把一个JavaBean转换成一个javabean，第一个JavaBean里的所有和第二个JavaBean相同名称
	 * 属性都会赋予第二个JavaBean的相应属性.
	 * 注意：属性类型只能是简单类型才能赋值
	 * @param <T>
	 * @param clazz
	 * @param rs
	 * @return
	 */
	public static <T1,T2> T1 getBeanFromBean(Class<T1> clazz, T2 fromBean) {

		try {

			T1 bean = clazz.newInstance();
			// Map<String, Object> nestedObjs = new HashMap<String,
			// Object>();
			Map<?, ?> map = PropertyUtils.describe(bean);
			Set<?> set = map.keySet();
			Iterator<?> i = set.iterator();

			while (i.hasNext()) {

				String name = (String) i.next();
				// System.err.println("bean:propertye:" + name);
				// Class t=PropertyUtils.getPropertyType(bean,name);
				// Object value=map.get(name);
				if (name.equals("class"))
					continue;

				Class<?> t = PropertyUtils.getPropertyType(bean, name);
				Object value = null;

				// name为javabean属性名
				if (SqlUtils.checkedSimpleType(t)) {// 简单类型

					value = PropertyUtils.getProperty(fromBean, name);
					PropertyUtils.setProperty(bean, name, value);
				} else {
					log.info("不识别的类型["+t.getSimpleName()+"]");
				}

			}// while

			return bean;
		} catch (Exception e) {
			log.error("", e);
		}
		return null;

	}
	public static String toJavascriptString(Object obj) throws Exception {
		
		String resultStr = "";
		if(obj==null) return "{}";
		if (obj.getClass().isPrimitive() || isPrimitiveWapper(obj.getClass()) ){
			return resultStr =resultStr+obj;
		}else if( obj.getClass()==String.class){
			if(((String)obj).startsWith("[javascript]")){
				return resultStr =StringUtils.trimLeadingString(obj+"", "[javascript]");
			}else{
			    return resultStr =resultStr+"\""+obj+"\"";
			}
		}else if(obj.getClass().isArray()){
			return ArrayUtils.toJavascriptString(obj);
		}else if(obj instanceof Map){
			return MapUtils.toJavascriptString((Map)obj);
		}else if(obj instanceof Collection){
			return CollectionUtils.toJavascriptString((Collection)obj);
		}
		
		Class c = obj.getClass();
	
		Field[] fields = c.getDeclaredFields();
		Map<String, Object> fieldsNameValues = new HashMap<String, Object>();
		Map<String, Field> fieldsNameField = new HashMap<String, Field>();
		String[] values = new String[fields.length];
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			field.setAccessible(true);
			int mod = field.getModifiers();
			if(Modifier.isStatic(mod)) continue;

			values[i] = field.getName();
			fieldsNameValues.put(field.getName(), field.get(obj));
			fieldsNameField.put(field.getName(), field);
		}
		try {

			for (int i = 0; i < values.length; i++) {
				String fieldName = values[i];

				Field field = fieldsNameField.get(fieldName);

				Object fvalue = field.get(obj);
				if (fvalue == null) {
					continue;
				}

				Class<?> fieldType = field.getType();

				// 基本类型
				if (fieldType.isPrimitive() || isPrimitiveWapper(fieldType) || 
						fieldType==String.class) {

					resultStr = resultStr + ",\"" + fieldName + "\":" + ObjectUtils.toJavascriptString(field.get(obj));

				} else if (fieldType.isArray()) {// 数组

					resultStr = resultStr +","
							+ ArrayUtils.toJavascriptString(field.get(obj));

				}else if(fvalue instanceof Map){
					resultStr = resultStr +","
					+ MapUtils.toJavascriptString((Map)field.get(obj));
					
				}else if(fvalue instanceof Collection){
				
					resultStr = resultStr +","
					+ CollectionUtils.toJavascriptString((Collection)field.get(obj));
				}
				else if (fieldType instanceof Object) {
					resultStr = resultStr +","+ ObjectUtils.toJavascriptString(obj);
				} else {
					throw new Exception("java bean里的" + fieldName + "属性的类型"
							+ fieldType + "不支持！");
				}

			}
		} catch (Exception e) {
			throw new Exception("seq属性配置不正确或者配置的javabean与二进制流格式不匹配导致解析出错");
		}

		return "{" + StringUtils.trimLeadingString(resultStr, ",") + "}";
	}

	public static String toJsonStringWithSupportJsFunction(Object obj) {

		JSONObject jsonObject = JSONObject.fromObject(obj);

		return jsonObject.toString();
	}

	/**
	 * 反射机制实现的深拷贝
	 * 
	 * @param obj
	 * @return
	 */
	public static <T> T CloneWithDeep(T object) {

		Cloner cloner = new Cloner();
		return cloner.deepClone(object);

		// return org.apache.commons.lang.ObjectUtils.clone(obj);
	}

	/**
	 * 反射机制实现的深拷贝
	 * 
	 * @param <T>
	 * @param object
	 *            需要深拷贝的类
	 * @param c
	 *            ：object中不需要拷贝的类,会设置为null
	 * @return
	 */
	public static <T> T CloneWithDeep(T object, java.lang.Class<?>... c) {

		Cloner cloner = new Cloner();
		// cloner.dontClone(c);
		cloner.nullInsteadOfClone(c);
		return cloner.deepClone(object);

		// return org.apache.commons.lang.ObjectUtils.clone(obj);
	}

	public static String toString(Object obj) {

		GsonBuilder builder = new GsonBuilder();
		builder.serializeNulls();
		builder.disableHtmlEscaping();
		builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
		builder.setPrettyPrinting();
		Gson gson = builder.create();
		return gson.toJson(obj);

		// StringWriter sw = new StringWriter();
		// JsonFactory jf = new JsonFactory();
		// ObjectMapper mapper = new ObjectMapper();
		// try {
		// JsonGenerator jg = jf.createJsonGenerator(sw);
		// jg.useDefaultPrettyPrinter();
		// mapper.writeValue(jg, obj);
		// } catch (Exception e) {
		// log.error("", e);
		// }
		// return sw.toString();

	}

	/**
	 * 
	 * @param obj
	 * @param type
	 *            用法如下： Type typeOfT = new
	 *            com.google.gson.reflect.TypeToken<Collection
	 *            <Foo>>(){}.getType();
	 * @return
	 */
	public static String toString(Object obj, Type type) {

		GsonBuilder builder = new GsonBuilder();
		builder.serializeNulls();
		builder.disableHtmlEscaping();
		builder.setPrettyPrinting();
		Gson gson = builder.create();
		return gson.toJson(obj, type);
	}

	public static void main(String[] args) throws Exception {
		// String s="{ 'Protocol' :123435,'ss':'abc', 'map':123 }";
		// // String s2=StringUtils.searchFirstSubStrByReg(s, reg, 1);
		// // System.out.println(s2);
		//
		// Type typeOfT = new
		// com.google.gson.reflect.TypeToken<HashMap<String,Object>>(){}.getType();
		// Map map =(Map) ObjectUtils.fromJsonToObject(s,typeOfT);
		// ObjectMapper mapper = new ObjectMapper();
		// String json="{"+
		// "\"name\" : { \"first\" : \"Joe\", \"last\" : \"Sixpack\" }, " +
		// "\"gender\" : 123, " +
		// "\"verified\" : false," +
		// "\"userImage\" : \"Rm9vYmFyIQ==\"}";
		// Map<String,Object> userData = mapper.readValue(json, Map.class);
		// System.out.println(ObjectUtils.toJsonString(userData));
		// CC ccc=new CC();
		// System.out.println(ObjectUtils.toJsonString(fromJavaBeanToMap(ccc)));
		// Map<String,String[]> map=new HashMap<String,String[]>();
		// map.put("ddd' ", new String[]{"'jj'<?#$%^\"&:^","dddd"});
		// System.out.println(ObjectUtils.toString(map));

		// AA aa=new AA();
		// Object bb=aa;
		// Object cc=ObjectUtils.CloneWithDeep(bb,BB[].class);
		// //cc.setName("");
		//
		// System.out.println("1"+ObjectUtils.toString(aa));
		// System.out.println("2"+ObjectUtils.toString(cc));
		// Map map=ObjectUtils.fromJavaBeanToMap(aa);
		// System.out.println(ObjectUtils.toString(map));
		// AA aa=new AA();
		// System.out.println(ObjectUtils.toJsonString(aa));
		// System.out.println(ObjectUtils.toJsonString(ObjectUtils.
		// fromJsonToObject(ObjectUtils.toJsonString(aa), AA.class)));

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("aa", "[javascript]123");
		map.put("b", true);
		map.put("c", "()");
		map.put("a", new int[] { 1, 2, 3 });
		System.out.println(ObjectUtils.toJavascriptString(map));

		String str = "{'string':'JSON', 'integer': 1, 'double': 2.0, 'boolean': true}";
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.registerJsonValueProcessor(String.class,
				new JsonValueProcessor() {

					@Override
					public Object processArrayValue(Object arg0, JsonConfig arg1) {
						// TODO Auto-generated method stub
						return "aa";
					}

					@Override
					public Object processObjectValue(String arg0, Object arg1,
							JsonConfig arg2) {
						// TODO Auto-generated method stub
						return "bb";
					}

				});
		JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(str,
				jsonConfig);
		System.out.println(jsonObject.toString());
		System.out.println(new HashMap<String,Object>() instanceof Map);
		
		// assertEquals( "JSON", jsonObject.getString("string") );
		// assertEquals( 1, jsonObject.getInt("integer") );
		// assertFalse( jsonObject.has("double") );
		// assertFalse( jsonObject.has("boolean") );

	}

}

